/* Copyright (c) 2008 LepomisLab.com, Andrey Turkin
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "NSView.h"
#include "NSKeyedUnarchiver.h"

IMPLEMENT_DYNAMIC_CLASS(NSView, NSResponder)

NSView::NSView() : NSResponder(), _superview(NULL), _window(NULL), _frame(), _flags(NSViewAutoresizes), _widget(NULL)
{
	_subviews = new NSMutableArray();
}

void NSView::initWithUnarchiver(NSKeyedUnarchiver *archiver)
{
	NSResponder::initWithUnarchiver(archiver);

	if (archiver->contains(wxT("NSFrame")))
	{
		wxRect* size = archiver->decodeRectForKey(wxT("NSFrame"));
		wxASSERT(size);
		_frame = *size;
	} else if (archiver->contains(wxT("NSFrameSize")))
	{
		wxSize *size = archiver->decodeSizeForKey(wxT("NSFrameSize"));
		_frame = *size;
	}

	archiver->decodeObjectForKey(wxT("NSPreviousKeyView"));
	archiver->decodeObjectForKey(wxT("NSNextKeyView"));

	if (archiver->contains(wxT("NSvFlags")))
		_flags = archiver->decodeIntForKey(wxT("NSvFlags"));

	wxObject *o = archiver->decodeObjectForKey(wxT("NSSubviews"));
	if (o)
	{
		delete _subviews;
		_subviews = wxDynamicCast(o, NSMutableArray);
		wxASSERT(_subviews);
	}
	archiver->decodeObjectForKey(wxT("NSSuperview"));
}

void NSView::_fixSubviews()
{
	NSMutableArray *_old_subviews = _subviews;
	_subviews = new NSMutableArray();
	for(size_t i=0;i < _old_subviews->length(); i++)
		{
			NSView *subview = wxDynamicCast(_old_subviews->getObject(i), NSView);
			wxASSERT(subview);
			if (subview->window() != this->window() || subview->superview() != this)
			{
//				subview->setWindow(this->window());
				addSubview(subview);
			} else
			{
				_subviews->addObject(subview);
			}
			subview->_fixSubviews();
		}
	delete _old_subviews;
}

void NSView::_willMoveToWindow(NSWindow *window)
{
	if (_window == window)
		return;
	_window = window;
	for(size_t i=0;i<_subviews->length();i++)
	{
		wxDynamicCast(_subviews->getObject(i), NSView)->_willMoveToWindow(window);
	}
}

void NSView::addSubview(NSView *subview)
{
	subview->removeFromSuperview();
	subview->_willMoveToWindow(_window);
	subview->_willMoveToSuperview(this);
	_subviews->addObject(subview);
}

void NSView::removeSubview(NSView *subview)
{
	subview->_superview = NULL;
	subview->_willMoveToWindow(NULL);
	subview->_willMoveToSuperview(NULL);
	//... remove from subviews...
}

void NSView::removeFromSuperview(void)
{
	if (_superview)
	{
		_superview->removeSubview(this);
	}
}

void NSView::_willMoveToSuperview(NSView* parent)
{
	if (parent == _superview)
		return;
	_superview = parent;
	_releaseWidget();
	_widget = _allocWidget(parent);
}

void NSView::_initWidget(wxWindow* widget)
{
	wxASSERT(_superview && _superview->widget());
	const wxRect& bounds = frame();
	wxPoint pos = bounds2wxPoint(_superview->widget(), bounds);
	widget->Move(pos);
	widget->SetSize(bounds.GetSize());
	widget->Show(true);
}

void NSView::setSize(const wxRect& newSize)
{
	if (_frame == newSize)
		return;

	if ((_flags & NSViewAutoresizes) != 0)
	{
		int dx = newSize.width - _frame.width;
		int dy = newSize.height - _frame.height;
		for(size_t i = 0; i < _subviews->length(); i++)
		{
			NSView* subview = wxDynamicCast(_subviews->getObject(i), NSView);
			wxASSERT(subview);
			wxRect subviewSize = subview->frame();
			unsigned int options = 0;
			if (subview->_flags & NSViewWidthSizable) options++;
			if (subview->_flags & NSViewMinXMargin)   options++;
			if (subview->_flags & NSViewMaxXMargin)   options++;
			if (options)
			{
				int change = dx/options;
				if (subview->_flags & NSViewWidthSizable)
					subviewSize.width += change;
				if (subview->_flags & NSViewMinXMargin)
					subviewSize.x += change;
			}
			options = 0;
			if (subview->_flags & NSViewHeightSizable) options++;
			if (subview->_flags & NSViewMinYMargin)   options++;
			if (subview->_flags & NSViewMaxYMargin)   options++;
			if (options)
			{
				int change = dy/options;
				if (subview->_flags & NSViewHeightSizable)
					subviewSize.height += change;
				if (subview->_flags & NSViewMinYMargin)
					subviewSize.y += change;
			}
			subview->setSize(subviewSize);
		}
	}
	_frame = newSize;
}

void NSView::_setValue(const wxString& key, wxObject *value)
{
	if (key == wxT("nextKeyView"))
	{
	} else
		NSResponder::_setValue(key, value);
}

wxObject* NSView::_getValue(const wxString& key)
{
	return NSResponder::_getValue(key);
}
